package com.leetCode.problem;


import java.util.concurrent.CountDownLatch;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Description:
 * Copyright:   Copyright (c)2019
 * Company:     zefu
 *
 * @author: 张李鑫
 * @version: 1.0
 * Create at:   2021-12-24 14:48:09
 * <p>
 * Modification History:
 * Date         Author      Version     Description
 * ------------------------------------------------------------------
 * 2021-12-24     张李鑫                     1.0         1.0 Version
 */
public class Problem5 {
    /**
     * 给你一个字符串 s，找到 s 中最长的回文子串。
     */

    public static String longestPalindrome(String s) {

        char[] manacherStr = getManacherStr(s);
        //创建回文半径数组
        int[] pArr = new int[manacherStr.length];
        //准备r 最右边边界 m当前中心点
        int r = -1;
        int c = -1;
        int max = -1;
        int index = 0;
        //开启循环
        for (int i = 0; i < manacherStr.length; i++) {
            // 如果i大于最右边的r 给一个1（最小半径是1）
            // 如果i在右边界里面  Math.min(pArr[2 * c - i], r - i) ｜  c-（i-c）｜｜r-i 不去判断 在后续循环直接判断
            pArr[i] = r > i ? Math.min(pArr[2 * c - i], r - i) : 1;
            while (i + pArr[i] < manacherStr.length && i - pArr[i] >= 0 && manacherStr[i + pArr[i]] == manacherStr[i - pArr[i]]) {
                pArr[i]++;
            }
            //如果大于了 就要更新r 跟c 顺便更新最大值
            if (i + pArr[i] > r) {
                r = i + pArr[i];
                c = i;
                if (max < pArr[i]) {
                    max = Math.max(max, pArr[i]);
                    index = i;
                }
            }
        }
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = index - pArr[index] + 1; i < index + pArr[index]; i++) {
            if (manacherStr[i] != '#') {
                stringBuilder.append(manacherStr[i]);
            }
        }
        return stringBuilder.toString();
    }


    /**
     * @return
     */
    public static int manacher(String str) {
        //把原先的字符串处理成manacherStr
        char[] manacherStr = getManacherStr(str);
        //创建回文半径数组
        int[] pArr = new int[manacherStr.length];
        //准备r 最右边边界 m当前中心点
        int r = -1;
        int c = -1;
        int max = -1;
        //开启循环
        for (int i = 0; i < manacherStr.length; i++) {
            // 如果i大于最右边的r 给一个1（最小半径是1）
            // 如果i在右边界里面  Math.min(pArr[2 * c - i], r - i) ｜  c-（i-c）｜｜r-i 不去判断 在后续循环直接判断
            pArr[i] = r > i ? Math.min(pArr[2 * c - i], r - i) : 1;
            while (i + pArr[i] < manacherStr.length && i - pArr[i] >= 0 && manacherStr[i + pArr[i]] == manacherStr[i - pArr[i]]) {
                pArr[i]++;
            }
            //如果大于了 就要更新r 跟c 顺便更新最大值
            if (i + pArr[i] > r) {
                r = i + pArr[i];
                c = i;
                max = Math.max(max, pArr[i]);
            }

        }
        return max - 1;
    }

    public static char[] getManacherStr(String s) {
        StringBuilder stringBuilder = new StringBuilder();
        char[] chars = s.toCharArray();
        for (char aChar : chars) {
            stringBuilder.append(aChar).append("#");
        }
        return stringBuilder.toString().toCharArray();
    }

    public static String longestPalindrome1(String str) {
        if (str == null || str.length() == 0) {
            return "";
        }
        char[] charArr = manacherString(str);
        int[] pArr = new int[charArr.length];
        int index = -1;
        int pR = -1;
        int max = Integer.MIN_VALUE;
        int mid = 0;
        for (int i = 0; i != charArr.length; i++) {
            pArr[i] = pR > i ? Math.min(pArr[2 * index - i], pR - i) : 1;
            while (i + pArr[i] < charArr.length && i - pArr[i] > -1) {
                if (charArr[i + pArr[i]] == charArr[i - pArr[i]])
                    pArr[i]++;
                else {
                    break;
                }
            }
            if (i + pArr[i] > pR) {
                pR = i + pArr[i];
                index = i;
            }
            if (max < pArr[i]) {
                max = pArr[i];
                mid = i;
            }
        }
        mid = (mid - 1) / 2;
        max = max - 1;
        return str.substring((max & 1) == 0 ? mid - (max / 2) + 1 : mid - (max / 2), mid + (max / 2) + 1);
    }

    public static char[] manacherString(String str) {
        char[] charArr = str.toCharArray();
        char[] res = new char[str.length() * 2 + 1];
        int index = 0;
        for (int i = 0; i != res.length; i++) {
            res[i] = (i & 1) == 0 ? '#' : charArr[index++];
        }
        return res;
    }

    public static int right(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }
        char[] str = getManacherStr(s);
        int max = 0;
        for (int i = 0; i < str.length; i++) {
            int L = i - 1;
            int R = i + 1;
            while (L >= 0 && R < str.length && str[L] == str[R]) {
                L--;
                R++;
            }
            max = Math.max(max, R - L - 1);
        }
        return max / 2;
    }

    public static void main(String[] args) throws Exception {
        AtomicInteger count1 = new AtomicInteger();
        FutureTask<AtomicInteger> futureTask = new FutureTask(() -> {
            for (int i = 0; i < 100; i++) {
                count1.getAndIncrement();
            }
            return count1;
        });

        FutureTask<AtomicInteger> futureTask1 = new FutureTask(() -> {
            for (int i = 0; i < 100; i++) {
                count1.getAndIncrement();
            }
            return count1;
        });


        FutureTask<AtomicInteger> futureTask2 = new FutureTask(() -> {
            for (int i = 0; i < 100; i++) {
                count1.getAndIncrement();
            }
            return count1;
        });

        Thread thread = new Thread(futureTask);
        thread.start();


        Thread thread1 = new Thread(futureTask1);
        thread1.start();


        Thread thread2 = new Thread(futureTask2);
        thread2.start();


        AtomicInteger integer = futureTask.get();
        AtomicInteger integer1 = futureTask1.get();
        AtomicInteger integer2 = futureTask2.get();


        System.out.println(integer.get()+integer1.get()+integer2.get());
    }
}
